import 抽象语法树节点.*;
import 抽象语法树节点.后缀表达式.*;
import 抽象语法树节点.字面量类.*;
import 抽象语法树节点.表达式类.*;
import 抽象语法树节点.表达式类.二元运算类.*;
import 抽象语法树节点.表达式类.关系运算类.*;
import 抽象语法树节点.表达式类.匹值运算类.*;
import 抽象语法树节点.语句类.*;

import java.util.ArrayList;

public class Cymbol语言访问器 extends CymbolBaseVisitor<抽象语法树> {
    @Override
    public 抽象语法树 visitCompilationUnit(CymbolParser.CompilationUnitContext ctx) {
        var 结果 = new 编译单元();
        结果.定义 = new ArrayList<>();

        for (var child : ctx.children) {
            结果.定义.add(this.visit(child));
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    @Override
    public 抽象语法树 visitStructDeclaration(CymbolParser.StructDeclarationContext ctx) {
        var 结果 = new 结构体定义(ctx.ID().getSymbol());
        结果.成员 = new ArrayList<>();

        for (var member : ctx.structMember()) {
            结果.成员.add(this.visit(member));
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    @Override
    public 抽象语法树 visitFieldDeclaration(CymbolParser.FieldDeclarationContext ctx) {
        var 结果 = new 变量定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());

        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitFieldArrayDeclaration(CymbolParser.FieldArrayDeclarationContext ctx) {
        var 结果 = new 数组定义(ctx.ID().getSymbol());
        结果.元素类型 = (类型引用) visit(ctx.type());

        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitInnerStructDeclaration(CymbolParser.InnerStructDeclarationContext ctx) {
        return visit(ctx.structDeclaration());
    }


    @Override
    public 抽象语法树 visitMethodDeclaration(CymbolParser.MethodDeclarationContext ctx) {
        var 结果 = new 方法定义(ctx.ID().getSymbol());
        结果.返回值类型 = (类型引用) visit(ctx.type());

        if (ctx.formalParameters() != null) {
            结果.参数列表 = (参数列表) visit(ctx.formalParameters());
        }

        结果.代码块 = (代码块) visit(ctx.block());

        结果.设置Token范围(ctx);
        return 结果;
    }


    @Override
    public 抽象语法树 visitFormalParameters(CymbolParser.FormalParametersContext ctx) {
        var 结果 = new 参数列表();
        结果.参数 = new ArrayList<>();

        for (var param : ctx.parameter()) {
            结果.参数.add(this.visit(param));
        }

        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitVarParam(CymbolParser.VarParamContext ctx) {
        var 结果 = new 变量定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitArrayParam(CymbolParser.ArrayParamContext ctx) {
        var 结果 = new 数组定义(ctx.ID().getSymbol());
        结果.元素类型 = (类型引用) visit(ctx.type());
        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitBasicType(CymbolParser.BasicTypeContext ctx) {
        return new 类型引用(ctx.primitiveType().start, false).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitStructType(CymbolParser.StructTypeContext ctx) {
        return new 类型引用(ctx.ID().getSymbol(), true).设置Token范围(ctx);
    }


    @Override
    public 抽象语法树 visitBlock(CymbolParser.BlockContext ctx) {
        var 结果 = new 代码块();
        结果.语句 = new ArrayList<>();
        if (ctx.statement() != null) {
            for (var statement : ctx.statement()) {
                结果.语句.add(this.visit(statement));
            }
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    @Override
    public 抽象语法树 visitVarDecl(CymbolParser.VarDeclContext ctx) {
        var 结果 = new 变量定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());

        if (ctx.expression() != null) {
            结果.初始值 = visit(ctx.expression());
        }

        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitArrayDecl(CymbolParser.ArrayDeclContext ctx) {
        var 结果 = new 数组定义(ctx.ID().getSymbol());
        结果.元素类型 = (类型引用) visit(ctx.type());

        if (ctx.expression() != null) {
            结果.初始值 = visit(ctx.expression());
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    // 语句类

    @Override
    public 抽象语法树 visitBlockStatement(CymbolParser.BlockStatementContext ctx) {
        return visit(ctx.block());
    }

    @Override
    public 抽象语法树 visitStrcutStatement(CymbolParser.StrcutStatementContext ctx) {
        return visit(ctx.structDeclaration());
    }

    @Override
    public 抽象语法树 visitVarStatement(CymbolParser.VarStatementContext ctx) {
        return visit(ctx.varDeclaration());
    }

    @Override
    public 抽象语法树 visitIfStatement(CymbolParser.IfStatementContext ctx) {
        var 结果 = new 判断语句();
        结果.条件 = visit(ctx.condition);
        结果.真值语句 = visit(ctx.trueStatement);

        if (ctx.falseStatement != null) {
            结果.假值语句 = visit(ctx.falseStatement);
        }

        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitReturnStatement(CymbolParser.ReturnStatementContext ctx) {
        var 结果 = new 返回语句();
        if (ctx.expression() != null) {
            结果.返回值 = visit(ctx.expression());
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    @Override
    public 抽象语法树 visitAssignStatement(CymbolParser.AssignStatementContext ctx) {
        var 结果 = new 赋值语句();
        结果.左值 = visit(ctx.postfixExpression());
        结果.右值 = visit(ctx.expression());
        结果.设置Token范围(ctx);
        return 结果;
    }

    @Override
    public 抽象语法树 visitCallStatement(CymbolParser.CallStatementContext ctx) {
        return visit(ctx.postfixExpression());
    }


    @Override
    public 抽象语法树 visitExpressionList(CymbolParser.ExpressionListContext ctx) {
        var 结果 = new 表达式列表();
        结果.表达式 = new ArrayList<>();
        for (var expression : ctx.expression()) {
            结果.表达式.add(visit(expression));
        }

        结果.设置Token范围(ctx);
        return 结果;
    }


    // 表达式类

    @Override
    public 抽象语法树 visitCallExpression(CymbolParser.CallExpressionContext ctx) {
        return visit(ctx.postfixExpression());
    }

    @Override
    public 抽象语法树 visitMinusExpression(CymbolParser.MinusExpressionContext ctx) {
        return new 负数表达式(visit(ctx.expression())).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitNotExpression(CymbolParser.NotExpressionContext ctx) {
        return new 取反表达式(visit(ctx.expression())).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitMultiplicationExpression(CymbolParser.MultiplicationExpressionContext ctx) {
        return new 乘法表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitDivisionExpression(CymbolParser.DivisionExpressionContext ctx) {
        return new 除法表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitAddExpression(CymbolParser.AddExpressionContext ctx) {
        return new 加法表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitSubtractionExpression(CymbolParser.SubtractionExpressionContext ctx) {
        return new 减法表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitLessThenExpression(CymbolParser.LessThenExpressionContext ctx) {
        return new 小于表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitGreaterThenExpression(CymbolParser.GreaterThenExpressionContext ctx) {
        return new 大于表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitLessOrEqualExpression(CymbolParser.LessOrEqualExpressionContext ctx) {
        return new 小于等于表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitGreaterOrEqualExpression(CymbolParser.GreaterOrEqualExpressionContext ctx) {
        return new 大于等于表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitNotEqualExpression(CymbolParser.NotEqualExpressionContext ctx) {
        return new 不等于表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitEqualExpression(CymbolParser.EqualExpressionContext ctx) {
        return new 相等表达式(visit(ctx.expression(0)), visit(ctx.expression(1))).设置Token范围(ctx);
    }


    // 后缀表达式类


    @Override
    public 抽象语法树 visitPrimary(CymbolParser.PrimaryContext ctx) {
        if (ctx.ID() != null) {
            return new 标识符(ctx.ID().getSymbol()).设置Token范围(ctx);
        } else if (ctx.INT() != null) {
            return new 整数型字面量(ctx.INT().getSymbol()).设置Token范围(ctx);
        } else if (ctx.CHAR() != null) {
            return new 字符型字面量(ctx.CHAR().getSymbol()).设置Token范围(ctx);
        } else if (ctx.FLOAT() != null) {
            return new 浮点型字面量(ctx.FLOAT().getSymbol()).设置Token范围(ctx);
        } else if (ctx.BOOL() != null) {
            return new 逻辑型字面量(ctx.BOOL().getSymbol()).设置Token范围(ctx);
        } else {
            return visit(ctx.expression());
        }
    }

    @Override
    public 抽象语法树 visitFunctionCall(CymbolParser.FunctionCallContext ctx) {
        var 结果 = new 方法调用表达式();
        结果.token = ctx.start;
        if (ctx.expressionList() != null) {
            结果.参数 = (表达式列表) visit(ctx.expressionList());
        }

        return 结果.设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitArrayAccess(CymbolParser.ArrayAccessContext ctx) {
        var 结果 = new 数组访问表达式();
        结果.token = ctx.start;
        结果.下标 = visit(ctx.expression());
        return 结果.设置Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitMemberAccess(CymbolParser.MemberAccessContext ctx) {
        return new 成员访问表达式(ctx.ID().getSymbol()).设置Token范围(ctx);
    }


    @Override
    public 抽象语法树 visitPostfixExpression(CymbolParser.PostfixExpressionContext ctx) {
        if (ctx.primary() != null) {
            return visit(ctx.primary());
        }

        var 对象 = visit(ctx.postfixExpression());
        var 后缀表达式 = visit(ctx.postfix());

        if (后缀表达式 instanceof 方法调用表达式 函数调用) {
            函数调用.函数 = 对象;
        } else if (后缀表达式 instanceof 成员访问表达式 成员访问) {
            成员访问.对象 = 对象;
        } else if (后缀表达式 instanceof 数组访问表达式 数组访问) {
            数组访问.数组 = 对象;
        }

        return 后缀表达式.设置Token范围(ctx);
    }
}
